import { BehaviourData, GameObjectData, InspectorData } from "../typings";
import { Behaviour } from "./Behaviour";
import { BitmapRenderer } from "./BitmapRenderer";
import { GameObject } from "./GameObject";
import { System } from "./System";
import { Transform } from "./Transform";
import { RigidBody } from "../RigidBody";
import { BoxCollider, CircleCollider, EdgeCollider } from "./Collider";
import { LifeCollider } from "../LifeCollider";


export class EditorSystem extends System {

    private webSocketClient: WebSocket;

    selectGameObject(gameObjectUUID: number) {
        console.log(`选中了${gameObjectUUID}`);
        const inspectorData = this.getInspectorData(gameObjectUUID);
        const message = {
            type: 'inspector',
            data: inspectorData
        };
        this.webSocketClient.send(JSON.stringify(message));
    }

    updateBehaviourData(data: BehaviourData) {
        const behaviour = Behaviour.get(data.uuid);
        for (let { key, value } of data.properties) {
            behaviour[key] = value;
        }
    }

    removeOneGameObject(gameObjectUUID: number) {

        const gameObject = GameObject.get(gameObjectUUID);
        const parent = gameObject.parent;
        parent.removeChild(gameObject);


    }

    serializeScene() {
        function serializeGameObject(gameObject: GameObject, object: any) {

            if (gameObject.id) {
                object.id = gameObject.id;
            }

            for (const behaviour of gameObject.behaviours) {
                const metadatas = (behaviour as any).constructor.propertiesMetaData;
                const behaviourObject = {
                    name: (behaviour as any).constructor.name,
                    properties: {}
                };
                if (metadatas) {
                    for (let metadata of metadatas) {
                        behaviourObject.properties[metadata.name] = behaviour[metadata.name];
                    }
                }

                object.behaviours.push(behaviourObject);
            }
            for (let child of gameObject.children) {
                const childObject: any = {};
                childObject.behaviours = [];
                childObject.children = [];
                serializeGameObject(child, childObject);
                object.children.push(childObject);
            }
        }
        const object: any = {};
        object.behaviours = [];
        object.children = [];
        serializeGameObject(this.rootGameObject, object);

        const content = JSON.stringify(object, null, '\t');
        console.log('序列化结果', content);
        return content;
    }

    onStart() {

        const webSocketClient = new WebSocket('ws://localhost:2018');
        this.webSocketClient = webSocketClient;

        webSocketClient.onopen = () => {
            {
                console.log('websocketopen');

                this.updateHierarchyDataSignal();
            }

            webSocketClient.onmessage = (event) => {
                const data = JSON.parse(event.data);
                if (data.type === 'selectGameObject') {
                    this.selectGameObject(data.uuid);
                }
                else if (data.type === 'updateBehaviourData') {
                    this.updateBehaviourData(data.behaviourData);
                }
                else if (data.type === 'serializeScene') {
                    const result = this.serializeScene();
                    this.webSocketClient.send(JSON.stringify({ type: 'saveScene', content: result }));
                }
                else if (data.type === 'deleteGameObject') {
                    this.removeOneGameObject(data.uuid);
                    this.updateHierarchyDataSignal();
                }
            };
        };


        const button1 = document.getElementById("addSplinter");
        console.log("button", button1);
        button1.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);
            var objId1 = "obstacle"
            childgameObject.id = objId1
            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/splinter.png"
            behaviour2.offsetX = -12.5
            behaviour2.offsetY = -12.5
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.25;
            behaviour3.y = -0.25;
            behaviour3.sensor = true;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 0.5;

            const behaviour5 = new LifeCollider();
            childgameObject.addBehaviour(behaviour5);


            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button2 = document.getElementById("addBrick1");
        console.log("button", button2);
        button2.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene1/brick1.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = false;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button3 = document.getElementById("addDiamond");
        console.log("button", button3);
        button3.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            var objId3 = "reward"
            childgameObject.id = objId3

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);
            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene1/diamond.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = true;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const behaviour5 = new LifeCollider();
            behaviour5.money = 2;
            childgameObject.addBehaviour(behaviour5);

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button4 = document.getElementById("addGold");
        console.log("button", button4);
        button4.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            var objId4 = "reward"
            childgameObject.id = objId4

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene1/gold.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = true;

            const behaviour4 = new CircleCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.radius = 0.5;

            const behaviour5 = new LifeCollider();
            behaviour5.money = 1;
            childgameObject.addBehaviour(behaviour5);

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button5 = document.getElementById("addStone");
        console.log("button", button5);
        button5.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            var objId5 = "obstacle"
            childgameObject.id = objId5

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene1/stone.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -31
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = true;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const behaviour5 = new LifeCollider();
            childgameObject.addBehaviour(behaviour5);

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button6 = document.getElementById("addBrick2");
        console.log("button", button6);
        button6.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene1/brick2.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = false;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button7 = document.getElementById("addFloor");
        console.log("button", button7);
        button7.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            const behaviour1 = new Transform();
            childgameObject.addBehaviour(behaviour1);
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1

            const behaviour2 = new RigidBody();
            childgameObject.addBehaviour(behaviour2);
            behaviour2.type = 0;
            behaviour2.x = 0;
            behaviour2.y = -1;
            behaviour2.sensor = false;

            const behaviour3 = new EdgeCollider();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.startX = 0;
            behaviour3.startY = 0;
            behaviour3.endX = 1;
            behaviour3.endY = 0;

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button8 = document.getElementById("addIce");
        console.log("button", button8);
        button8.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene2/ice.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = false;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button9 = document.getElementById("addGoldshell");
        console.log("button", button9);
        button9.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            var objId9 = "reward"
            childgameObject.id = objId9

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene2/beike2.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = true;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const behaviour5 = new LifeCollider();
            behaviour5.money = 1;
            childgameObject.addBehaviour(behaviour5);


            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button10 = document.getElementById("addPurpleshell");
        console.log("button", button10);
        button10.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            var objId10 = "reward"
            childgameObject.id = objId10

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene2/beike.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = true;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const behaviour5 = new LifeCollider();
            behaviour5.money = 1;
            childgameObject.addBehaviour(behaviour5);


            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button11 = document.getElementById("addRock");
        console.log("button", button11);
        button11.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene3/cube.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = false;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button12 = document.getElementById("addWater");
        console.log("button", button12);
        button12.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            var objId12 = "reward"
            childgameObject.id = objId12

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene3/shuidi.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = true;

            const behaviour4 = new BoxCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.edge = 1;

            const behaviour5 = new LifeCollider();
            behaviour5.money = 1;
            childgameObject.addBehaviour(behaviour5);


            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };

        const button13 = document.getElementById("addMouster");
        console.log("button", button13);
        button13.onclick = () => {
            const childgameObject = new GameObject();
            const rootGameObject = this.engine.getGameObject("background");
            console.log("创建：", rootGameObject);
            rootGameObject.addChild(childgameObject);

            var objId13 = "obstacle"
            childgameObject.id = objId13

            const behaviour1 = new Transform();
            behaviour1.x = 0;
            behaviour1.y = 0;
            behaviour1.scaleX = 1;
            behaviour1.scaleY = 1;
            behaviour1.rotation = 0;
            behaviour1.alpha = 1
            childgameObject.addBehaviour(behaviour1);

            const behaviour2 = new BitmapRenderer();
            behaviour2.source = "assets/scene3/heimeiqiu.png"
            behaviour2.offsetX = -25
            behaviour2.offsetY = -25
            childgameObject.addBehaviour(behaviour2);

            const behaviour3 = new RigidBody();
            childgameObject.addBehaviour(behaviour3);
            behaviour3.type = 0;
            behaviour3.x = 0.5;
            behaviour3.y = -0.5;
            behaviour3.sensor = true;

            const behaviour4 = new CircleCollider();
            childgameObject.addBehaviour(behaviour4);
            behaviour4.radius = 0.5;

            const behaviour5 = new LifeCollider();
            behaviour5.money = 0;
            childgameObject.addBehaviour(behaviour5);

            const hierarchyData = this.getHierarchyData();
            const message = {
                type: 'hierarchy',
                data: hierarchyData
            }
            this.webSocketClient.send(JSON.stringify(message));

        };


    }


    updateHierarchyDataSignal() {
        //发送信号给editor/index.ts 要更新a面板
        const hierarchyData = this.getHierarchyData();
        const message = {
            type: 'hierarchy',
            data: hierarchyData
        };
        this.webSocketClient.send(JSON.stringify(message));

    }


    getHierarchyData() {
        function serializeHierarchy(gameObject: GameObject, obj: GameObjectData) {
            obj.uuid = gameObject.uuid;
            obj.name = gameObject.name;
            obj.children = gameObject.children.map((child) => {
                const childObj: any = {};

                serializeHierarchy(child, childObj);
                return childObj;
            });
        }
        const obj: GameObjectData = {
            uuid: 0,
            name: '',
            children: [],
            behaviours: []
        };
        serializeHierarchy(this.rootGameObject, obj);
        return obj;
    }

    getInspectorData(gameObjectUUID: number): InspectorData {
        const gameObject = GameObject.get(gameObjectUUID);
        const array: InspectorData = [];
        for (const behaviour of gameObject.behaviours) {
            const metadatas = (behaviour as any).constructor.propertiesMetaData;
            const behaviourObject: BehaviourData = {
                uuid: behaviour.uuid,
                name: (behaviour as any).constructor.name,
                properties: []
            };
            if (metadatas) {
                for (let metadata of metadatas) {
                    behaviourObject.properties.push(
                        { key: metadata.name, value: behaviour[metadata.name], type: metadata.type }
                    );
                }
            }

            array.push(behaviourObject);
        }
        return array;
    }
}
